package web.reader;

import function.unary.UnaryFunction;
import java.util.ArrayList;
import java.util.List;
import list.functions.ListFunctions;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Shimu
 * @date 16-Sep-2012
 */
public class Webpage {

    private final ArrayList<String> CONTENT;

    private static final UnaryFunction<String, Boolean> isDocType,
            isTitle, isLink, isParagraph, isMeta;

    static {
        // Returns true if the given String starts with "<!DOCTYPE"
        isDocType = getPredicate("<!DOCTYPE");

        // Returns true if the given String starts with "<title>"
        isTitle = getPredicate("<title>");

        // Returns true if the given String starts with "<link"
        isLink = getPredicate("<link");

        // Returns true if the given String starts with "<p>"
        isParagraph = getPredicate("<p>");

        // Returns true if the given String starts with "<meta>"
        isMeta = getPredicate("<meta");
    }

    /**
     * Returns a UnaryFunction<String, Boolean> (i.e. a predicate) that will
     * return true if a given String starts with the given startStr.
     * 
     * @param startStr
     * @return 
     */
    private static UnaryFunction<String, Boolean> getPredicate(
            final String startStr) {
        return new UnaryFunction<String, Boolean>() {

            public Boolean evaluate(String arg) {
                return arg.startsWith(startStr);
            }
        };
    }

    /**
     * Given a URL, attempt to connect to the URL and return the content
     * of the URL. 
     * 
     * @param <T> the return type of the ContentAccumulator
     * @param url the URL to retrieve information from
     * @param ac the ContentAccumulator used to retrieve information from the
     * URL
     * @return 
     * 
     * @throws MalformedURLException if the given URL was invalid
     * @throws IOException if an error occurred while trying to connect or
     * retrieve information from the given URL.
     */
    private static ArrayList<String> readURL(String url) throws
            MalformedURLException, IOException {
        URL webpage = new URL(url);
        BufferedReader in =
                new BufferedReader(new InputStreamReader(webpage.openStream()));

        ArrayList<String> list = new ArrayList<String>();
        String line;
        while ((line = in.readLine()) != null) {
            list.add(line);
        }

        in.close();
        return list;
    }

    public Webpage(String url) throws MalformedURLException, IOException {
        this.CONTENT = readURL(url);
    }

    /**
     * Returns the content of this webpage in HTML format.
     * @return 
     */
    public ArrayList<String> getRawContent() {
        return CONTENT;
    }

    /**
     * Returns the doc type of the webpage, null if no doc type was found.
     * The doc type is the line that starts with !DOCTYPE
     * @return 
     */
    public String getDocType() {
        return ListFunctions.find(isDocType, CONTENT.subList(0, 2));
    }

    /**
     * Returns the title of the webpage, null if no title was found.
     * The title is the line that is enclosed by the tags <title> and </title>
     * @return 
     */
    public String getTitle() {
        return ListFunctions.find(isTitle, CONTENT.subList(0, 10));
    }

    /**
     * Returns all the meta in this webpage. 
     * (Anything inside a <meta> symbol)
     * @return 
     */
    public List<String> getMetas() {
        return ListFunctions.filter(isMeta, CONTENT);
    }

    /**
     * Returns all the links in this webpage. 
     * (Anything inside a <link> symbol)
     * @return 
     */
    public List<String> getLinks() {
        return ListFunctions.filter(isLink, CONTENT);
    }

    /**
     * Returns all the paragraphs in this webpage. 
     * (Anything in between <p> </p> symbols).
     * 
     * @return 
     */
    public List<String> getParagraphs() {
        return ListFunctions.filter(isParagraph, CONTENT);
    }
    
    
    private static final Pattern scriptPattern =
            Pattern.compile("<script src=\"(.+)\"></script>");

    /**
     * If the given htmlLine is of the form:
     * &lt; script src="src_url" &gt; &lt; /script &gt;
     * returns src_url.
     * 
     * @param htmlLine
     * @return 
     */
    private String getSrcScript(String htmlLine) {
        Matcher m = scriptPattern.matcher(htmlLine);
        if (m.matches()) {
            return m.group(1);
        } else {
            return null;
        }
    }

    public ArrayList<String> getScripts() {
        ArrayList<String> scripts = new ArrayList<String>();
        for (String line : CONTENT) {
            String src = getSrcScript(line);
            
        }
        return scripts;
    }
    
    /*
    public ArrayList<String> getContentBetweenTags(
            ArrayList<String> content, String tag) {
        Pattern startPattern = Pattern.compile("<" + tag + ">");
        Pattern endPattern = Pattern.compile("</" + tag + ">");
        
        for (String line : content) {
            if (line.startsWith(line))
        }
    }*/
}
